package main
import (
	"fmt"
    "math"
)

type Employee struct {
    name string
    salary int
    currency string
    age  int
}
// 方法示例
func (e Employee) displaySalary() {
    fmt.Printf("\n 方法 Salary of %s is %s%d", e.name, e.currency, e.salary)
}
// 上面的程序已经被重写为只使用函数，没有方法。
func displaySalary(e Employee) {
    fmt.Printf("\n 函数 Salary of %s is %s%d", e.name, e.currency, e.salary)
}

// 17. 方法  方法不是函数
func main(){
    emp1 := Employee{"yanghao", 5000, "$", 10}
    emp1.displaySalary() //方法
    displaySalary(emp1) //函数

    // 既然我们可以使用函数写出相同的程序，那么为什么我们需要方法？这有着几个原因，让我们一个个的看看。
        // Go 不是纯粹的面向对象编程语言，而且Go不支持类。因此，基于类型的方法是一种实现和类相似行为的途径。
        // 相同的名字的方法可以定义在不同的类型上，而相同名字的函数是不被允许的。
        // 假设我们有一个 Square 和 Circle 结构体。可以在 Square 和 Circle 上分别定义一个 Area 方法。见下面的程序。
    r := Rectangle{
        length: 10,
        width: 5,
    }
    fmt.Println("\n Rectangle=", r.Area())
    c := Circle{
        redius: 10,
    }
    fmt.Println("Circle=", c.Area())

    // 指针接收器与值接收器
    e := Employee{
        name: "Mark Andrew",
        age:  50,
    }
    fmt.Printf("Employee name before change: %s", e.name)
    e.changeName("Michael Andrew")
    fmt.Printf("\nEmployee name after change: %s", e.name)
    fmt.Printf("\n\nEmployee age before change: %d", e.age)
    e.changeAge(51)
    fmt.Printf("\nEmployee age after change: %d", e.age)

    // 匿名字段的方法
    p := person{
        firstName: "yang",
        lastName: "hao",
        address: address {
            city: "广州",
            state: "超级好",
        },
    }
    p.fullAddress()


    num1 := myInt(5)
    num2 := myInt(10)
    sum := num1.add(num2)

    fmt.Println("\nnum1 = ", num1)
    fmt.Println("num2 = ", num2)
    fmt.Println("sum = ", sum)


}


type Rectangle struct {
    length int
    width int
}
type Circle struct {
    redius float64
}
// 方法 可以同名 不同的类型
func (r Rectangle) Area() int {
    return r.length * r.width
}
func (c Circle) Area() float64 {
    return math.Pi * c.redius * c.redius
}
// 使用值接收器的方法。
func (e Employee) changeName(newName string) {
    e.name = newName
}
// 使用指针接收器的方法。
func (e *Employee) changeAge(newAge int) {
    e.age = newAge
}

type address struct {
    city string
    state string
}
func (a address) fullAddress(){
    fmt.Printf("\n\nFull address: %s, %s", a.city, a.state)
}
type person struct {
    firstName string
    lastName string
    address
}

type myInt int
func (a myInt) add(b myInt) myInt{
    return a + b
}